<template>
  <div class="wrapper" ref="relationRef"></div>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue';
import * as echarts from 'echarts';
import plotdata from './plot.json';

// 定义组件的 props
const props = defineProps({
  snv: {
    type: String,
    default: 'rs3817731'
  },
  plotData: {
    type: Object,
    default: () => plotdata
  }
});

// 图表DOM引用
const relationRef = ref(null);
// 图表实例
let chartInstance = null;

// 根据健康状态获取节点类别和颜色
const getCategoryAndColor = (healthStatus) => {
  if (healthStatus === 'cancer') {
    return { category: 'Cancer', color: '#2b78c2' };
  } else if (healthStatus === 'normal') {
    return { category: 'Normal', color: '#ff8c27' };
  } else if (healthStatus === 'both') {
    return { category: 'Both', color: '#3aaa35' };
  } else {
    return { category: 'SNV', color: '#d9534f' };
  }
};

// 初始化图表
const initChart = () => {
  if (!relationRef.value) return;
  
  // 创建ECharts实例
  chartInstance = echarts.init(relationRef.value);
  
  // 更新图表
  updateChart();
};

// 更新图表数据和配置
const updateChart = () => {
  if (!chartInstance) return;
  
  const { snv, plotData } = props;
  
  try {
    // 确保plotData是有效的数据数组
    const dataArray = Array.isArray(plotData) ? plotData : 
                    (plotData && typeof plotData === 'object' && Array.isArray(plotData.data)) ? 
                    plotData.data : [];
    
    // 处理数据，合并相同cpgPos但健康状态不同的节点
    const cpgPosMap = new Map();
    const nodeInfoMap = new Map();
    
    // 对数据按cpgPos分组
    dataArray.forEach((item) => {
      if (!item || !item.cpgPos) return;
      
      const cpgPos = item.cpgPos;
      const healthStatus = item.sampleInfo?.healthStatus?.toLowerCase() || '';
      const tissue = item.sampleInfo?.tissue || 'Unknown';
      
      // 存储详细信息
      if (!nodeInfoMap.has(cpgPos)) {
        nodeInfoMap.set(cpgPos, []);
      }
      nodeInfoMap.get(cpgPos).push({
        tissue: tissue,
        healthStatus: item.sampleInfo?.healthStatus || 'Unknown'
      });
      
      if (!cpgPosMap.has(cpgPos)) {
        cpgPosMap.set(cpgPos, new Set([healthStatus]));
      } else {
        cpgPosMap.get(cpgPos).add(healthStatus);
      }
    });
    
    // 取中心点
    const getCenterPos = () => {
      const width = relationRef.value ? relationRef.value.clientWidth : 560;
      const height = relationRef.value ? relationRef.value.clientHeight : 500;
      return {
        x: width * 0.5,
        y: height * 0.5
      };
    };
    
    // 计算环形布局位置
    const circledNodePosition = (centerX, centerY, index, nodesLen, radius = 180) => {
      const angle = (360 / nodesLen) * index * (Math.PI / 180);
      return {
        x: centerX + Math.sin(angle) * radius,
        y: centerY + Math.cos(angle) * radius
      };
    };
    
    // 准备节点和连接数据
    const nodes = [];
    const links = [];
    const center = getCenterPos();
    
    // 首先添加中心SNV节点
    nodes.push({
      id: snv,
      name: snv,
      symbolSize: 50,
      category: 0,
      itemStyle: {
        color: '#d9534f'
      },
      // 将SNV节点固定在圆心位置
      x: center.x,
      y: center.y,
      fixed: true
    });
    
    // 然后添加外围的CpG节点，形成圆环
    let index = 0;
    for (const [cpgPos, statusSet] of cpgPosMap.entries()) {
      let categoryIndex = 0;
      let color = '#d9534f';
      let healthStatus = 'Unknown';
      
      // 确定节点类别
      if (statusSet.has('cancer') && statusSet.has('normal')) {
        categoryIndex = 3; // Both
        color = '#3aaa35';
        healthStatus = 'Both';
      } else if (statusSet.has('cancer')) {
        categoryIndex = 1; // Cancer
        color = '#2b78c2';
        healthStatus = 'Cancer';
      } else if (statusSet.has('normal')) {
        categoryIndex = 2; // Normal
        color = '#ff8c27';
        healthStatus = 'Normal';
      }
      
      // 计算节点位置
      const position = circledNodePosition(center.x, center.y, index, cpgPosMap.size);
      
      // 添加CpG节点
      nodes.push({
        id: cpgPos,
        name: cpgPos,
        symbolSize: 35,
        category: categoryIndex,
        itemStyle: {
          color: color
        },
        // 添加坐标位置
        x: position.x,
        y: position.y,
        // 添加自定义数据，用于tooltip
        tooltip: {
          formatter: function(params) {
            const nodeInfo = nodeInfoMap.get(cpgPos) || [];
            let tissues = [...new Set(nodeInfo.map(info => info.tissue))].join(', ');
            
            return `<div>
              <p><strong>${cpgPos}</strong> (CpG)</p>
              <p>Tissue: ${tissues}</p>
              <p>Health Status: ${healthStatus}</p>
            </div>`;
          }
        }
      });
      
      index++;
    }
    
    // 添加连接，将SNV节点连接到所有CpG节点
    for (let i = 1; i < nodes.length; i++) {
      links.push({
        source: 0, // SNV节点的索引
        target: i,
        lineStyle: {
          color: '#aaa',
          opacity: 0.7,
          width: 1
        },
        // 添加箭头
        symbol: ['circle', 'arrow'],
        symbolSize: [4, 10]
      });
    }
    
    // 图表配置
    const option = {
      tooltip: {
        trigger: 'item',
        formatter: function(params) {
          if (params.dataType === 'node') {
            if (params.data.id === snv) {
              return `<div><strong>${snv}</strong> (SNV)</div>`;
            } else if (params.data.tooltip && params.data.tooltip.formatter) {
              return params.data.tooltip.formatter(params);
            }
          }
          return params.name;
        },
        backgroundColor: 'rgba(50,50,50,0.9)',
        borderColor: '#eee',
        borderWidth: 1,
        textStyle: {
          color: '#fff'
        }
      },
      legend: {
        data: ['SNV', 'Cancer', 'Normal', 'Both'],
        top: 10,
        left: 'center',
        orient: 'horizontal',
        itemWidth: 20,
        itemHeight: 10,
        textStyle: {
          fontSize: 12
        }
      },
      animationDurationUpdate: 1500,
      animationEasingUpdate: 'quinticInOut',
      series: [
        {
          name: 'SNV关系图',
          type: 'graph',
          layout: 'none', // 改为none布局，使用固定位置
          data: nodes,
          links: links,
          categories: [
            { name: 'SNV' },
            { name: 'Cancer' },
            { name: 'Normal' },
            { name: 'Both' }
          ],
          roam: true,
          label: {
            show: true,
            position: 'right',
            formatter: '{b}',
            fontSize: 12
          },
          lineStyle: {
            opacity: 0.9,
            width: 1,
            curveness: 0
          },
          itemStyle: {
            borderColor: '#fff',
            borderWidth: 0.5,
            shadowBlur: 3,
            shadowColor: 'rgba(0, 0, 0, 0.2)'
          },
          emphasis: {
            lineStyle: {
              width: 2
            },
            scale: true
          }
        }
      ],
      color: ['#d9534f', '#2b78c2', '#ff8c27', '#3aaa35']
    };
    
    // 设置图表配置
    chartInstance.setOption(option);
    
  } catch (error) {
    console.error('处理数据时出错:', error);
  }
};

// 监听props变化
watch(() => props.snv, updateChart);
watch(() => props.plotData, updateChart, { deep: true });

// 处理窗口大小变化
const handleResize = () => {
  chartInstance && chartInstance.resize();
};

// 生命周期钩子
onMounted(() => {
  initChart();
  window.addEventListener('resize', handleResize);
});

// 组件卸载前清理
const onBeforeUnmount = () => {
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
  }
  window.removeEventListener('resize', handleResize);
};
</script>

<style scoped>
.wrapper {
  width: 560px;
  height: 500px;
}
</style>